package org.fujene.diskblock.blockwise;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;

import org.fujene.diskblock.DiskBlock;
import org.fujene.memoryblock.MemoryBlock;
import org.fujene.memoryblock.blockwise.BlockwiseContentBlock;
import org.fujene.structure.Constants;
import org.fujene.structure.LookupPointer;
import org.fujene.toolbox.ByteConverter;

public class BlockwiseContentDiskBlock extends DiskBlock {

	public BlockwiseContentDiskBlock(File fileDesc) throws Exception {
		super(fileDesc);
	}

	public BlockwiseContentDiskBlock(BlockwiseContentBlock memBlock, String dir) {
		super(memBlock, dir);
	}

	public BlockwiseContentDiskBlock(int ID, File desc, int defaultBodySize,
			int defaultOptionSize) throws Exception {
		super(ID, desc, Constants.MEMORY_TYPE_CONTENTS, defaultBodySize,
				defaultOptionSize);
	}
	
	private class Contents {
		long ID;
		LookupPointer[] supps;
		int supplen;
		int strlen;
		String str;

		// 読み込み用
		public Contents(int from, boolean readStr) throws Exception {
			supplen = getOption(1);
			ID = ByteConverter.byteToLong(getBody(from, 8));
			from += 8;
			
			supps = new LookupPointer[getOption(1)];
			for (int i = 0; i < getOption(1); i++) {
				supps[i] = ByteConverter.getPtr(getBody(from, PTR));
				from += PTR;
			}

			if (readStr) {
				strlen = ByteConverter.byteToInt(getBody(from, STRLEN));
				from += STRLEN;

				try {
					str = new String(getBody(from, strlen), "UTF-8");
				} catch (UnsupportedEncodingException e) {
				}
			}
		}
	}

	public String getContent(int ptr) {
		Contents content;
		try {
			content = new Contents(ptr, true);
			return content.str;
		} catch (Exception e) {
			return null;
		}
	}

	public LookupPointer[] getSuppPtr(int ptr) {
		Contents content;
		try {
			content = new Contents(ptr, false);
			return content.supps;
		} catch (Exception e) {
			return null;
		}
	}

	public int getCount() throws Exception {
		return this.getOption(0);
	}
	
	public int getContentIndex(){
		try {
			return this.getOption(2);
		} catch (Exception e) {
			return -1;
		}
	}

	@Override
	public void readToMemory(MemoryBlock memBlock) {
		if (memBlock instanceof BlockwiseContentBlock) {
			try {
				memBlock.setOption(0, this.getOption(0));
				memBlock.setOption(1, this.getOption(1));
				memBlock.setOption(2, this.getOption(2));
				memBlock.setBody(this.getBody(0, this.bodySize), 0);
				memBlock.setBodyVacancy(this.bodyVacancy);
			} catch (Exception e) {
			}
		}
	}

	@Override
	public byte[] getData() throws Exception {
		ByteArrayOutputStream stream = new ByteArrayOutputStream(this.bodySize + 4);
		
		stream.write(ByteConverter.intToByte(this.getOption(0), 4));
		stream.write(ByteConverter.intToByte(this.getOption(1), 4));
		stream.write(ByteConverter.intToByte(this.getOption(2), 4));
		stream.write(this.getBody(0, this.bodySize));
		
		return stream.toByteArray();
	}
}
